package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import groovyjarjarpicocli.CommandLine;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author 陈彦祖
 * @since 2024-11-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final IInteractionReplyService replyService;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryClient categoryClient;
    private final CategoryCache categoryCache;


    /**
     * 1
     * 新增互动提问
     *
     * @param questionFormDTO
     */
    @Override
    public void saveQuestion(QuestionFormDTO questionFormDTO) {
        //1，拷贝数据
        InteractionQuestion question = BeanUtils.copyProperties(questionFormDTO, InteractionQuestion.class);
        //2，填充用户id
        question.setUserId(UserContext.getUser());
        //3，保存互动提问详情
        save(question);
    }

    /**
     * 2
     * 分页查询互动问题列表
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionVO> queryQuestionByPage(QuestionPageQuery query) {
        //1,先拿到课程id和小节id
        Long courseId = query.getCourseId();
        Long sectionId = query.getSectionId();
        //1.1,判断两个id不能都为空
        if (ObjectUtils.isEmpty(courseId) && ObjectUtils.isEmpty(sectionId)) {
            throw new BadRequestException("课程id和小节id不能同时为空");
        }
        //2,分页查询问题表
        //select * from interaction_question where course_id = #{} and section_id = #{}
        //and user_id = #{} and status = 1 and hidden = 0 order by create_time desc
        Page<InteractionQuestion> page = this.lambdaQuery()
                .select(InteractionQuestion.class, column -> !column.getColumn().equals("description"))
                .eq(ObjectUtil.isNotNull(courseId), InteractionQuestion::getCourseId, courseId)
                .eq(ObjectUtil.isNotNull(sectionId), InteractionQuestion::getSectionId, sectionId)
                .eq(BooleanUtils.isTrue(query.getOnlyMine()), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        //2.1,拿到集合
        List<InteractionQuestion> records = page.getRecords();
        //2.2,判断集合是否为空
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        //3，补充信息填充查询（非匿名）
        //3.1，收集id集合，最近的回答id
        Set<Long> userIds = new HashSet<>();
        Set<Long> latestAnswerIds = new HashSet<>();
        //3.2，遍历集合，收集信息
        for (InteractionQuestion record : records) {
            //3.3,判断是否匿名，不匿名，收集用户id
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            latestAnswerIds.add(record.getLatestAnswerId());
        }
        //3.4，根据id查询最近回答
        List<InteractionReply> lastReplyList = replyService.listByIds(latestAnswerIds);
        Map<Long, InteractionReply> replyMap = new HashMap<>(lastReplyList.size());
        if (ObjectUtils.isNotEmpty(lastReplyList)) {
            //3.5,匿名回答者id
            for (InteractionReply reply : lastReplyList) {
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
                replyMap.put(reply.getId(), reply);
            }
        }
        //3.6，根据id查询用户信息
        List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userInfoMap = new HashMap<>(userIds.size());
        if (ObjectUtils.isNotEmpty(userInfoList)) {
            userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        }
        // 4、循环遍历分页数据，封装VO集合
        List<QuestionVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion question : records) {
            // 4.1、将po转为vo
            QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
            // 4.2、补充提问者的信息（提问者昵称、头像）
            if (!question.getAnonymity()) {
                UserDTO userInfo = userInfoMap.get(question.getUserId());
                if (ObjectUtils.isNotEmpty(userInfo)) {
                    vo.setUserName(userInfo.getName());
                    vo.setUserIcon(userInfo.getIcon());
                }
            }
            // 4.3、补充最近一次回答者的信息（最近一次回答者的昵称、最近一次回答内容）
            InteractionReply lastReply = replyMap.get(question.getLatestAnswerId());
            if (ObjectUtils.isNotEmpty(lastReply)) {
                vo.setLatestReplyContent(lastReply.getContent());
                if (!lastReply.getAnonymity()) {
                    UserDTO userInfo = userInfoMap.get(lastReply.getUserId());
                    if (ObjectUtils.isNotEmpty(userInfo)) {
                        vo.setLatestReplyUser(userInfo.getName());
                    }
                }
            }
            // 4.4、添加至List
            voList.add(vo);
        }
        // 5、封装PageDTO并返回
        return PageDTO.of(page, voList);
    }

    /**3
     * 根据id查询互动问题
     * @param id
     * @return
     */
    @Override
    public QuestionVO queryById(Long id) {
        //1，根据id查询互动问题
        InteractionQuestion question = this.getById(id);
        //2，判断是否为空
        if (ObjectUtils.isEmpty(question) || question.getHidden()){
           return null;
        }
        //2.查询提问者信息
        UserDTO userInfo = null;
        if (!question.getAnonymity()){
            //2.1，查询用户信息
            userInfo = userClient.queryUserById(question.getUserId());
        }
        //3.拷贝封装vo并返回
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        //3.1，设置提问者信息
        if (ObjectUtils.isNotEmpty(userInfo)){
            vo.setUserName(userInfo.getName());
            vo.setUserIcon(userInfo.getIcon());
        }
        return vo;
    }
    /**4
     * 删除互动问题
     * @param id
     */
    @Override
    public void deleteQuestion(Long id) {
        //1,查询问题是否存在
        InteractionQuestion question = this.getById(id);
        if (ObjectUtils.isEmpty(question)){
            throw new BadRequestException("问题不存在");
        }
        //2,判断是否是当前用户提问的
        if (!UserContext.getUser().equals(question.getUserId())){
            throw new BadRequestException("只能删除自己的问题");
        }
        //3,如果不是则报错，如果是则删除问题
        this.removeById(id);
    }

    /**5
     * 修改互动问题
     * @param id
     * @param questionFormDTO
     */
    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionFormDTO) {
        //在课程详情页，或者用户学习视频页面，都可以点击自己提出的问题，修改问题标题、描述信息、是否匿名
        Long userId = UserContext.getUser();
        //1,查询问题是否存在
        InteractionQuestion question = this.getById(id);
        //1.1,判断是否为空
        if (ObjectUtils.isEmpty(question)){
            throw new BadRequestException("问题不存在");
        }
        //2,判断是否是当前用户提问的
        if (!userId.equals(question.getUserId())){
            throw new BadRequestException("只能修改自己的问题");
        }
        //3,修改问题
        question.setTitle(questionFormDTO.getTitle());
        question.setDescription(questionFormDTO.getDescription());
        question.setAnonymity(questionFormDTO.getAnonymity());
        this.updateById(question);
    }

    /**2
     * 管理端修改互动问题的隐藏状态
     * @param id
     * @param hidden
     */
    @Override
    public void updateHidden(Long id, Boolean hidden) {
        //1，修改状态
        boolean update = this.lambdaUpdate()
                .eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getHidden, hidden)
                .update();
        //判断是否修改成功
        if (!update){
            throw new BadRequestException("修改失败");
        }
        log.info("修改问题隐藏状态，id：{}，hidden：{}", id, hidden);

    }

    /**3
     * 管理端根据id查询问题详情
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO questionsQueryById(Long id) {
        //可以看到，这里需要查询的数据还是比较多的，包含：
        // 问题标题，问题描述，提问者信息，id，昵称，头像，课程三级分类，课程名称，课程负责老师，课程所属章节，回答数量，用户端是否显示
        //1，根据id查询问题详情
        InteractionQuestion question = this.getById(id);
        if (ObjectUtils.isEmpty(question)){
            return null;
        }
        //2，转换为VO
        QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
        //3，查询提问者信息
        UserDTO userInfo = userClient.queryUserById(question.getUserId());
        //3.1,判断是否为空
        if (ObjectUtils.isNotEmpty(userInfo)){
            vo.setUserName(userInfo.getName());
            vo.setUserIcon(userInfo.getIcon());
        }
        //4，查询课程信息
        CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(question.getCourseId(), false, false);
        //4.1，判断课程是否存在
        if (ObjectUtils.isNotEmpty(courseInfo)){
            vo.setCourseName(courseInfo.getName());
            vo.setCategoryName(categoryCache.getCategoryNames(courseInfo.getCategoryIds()));
            //4.2，查询课程负责老师
            List<Long> teacherIds = courseInfo.getTeacherIds();
            List<UserDTO> teacherInfos = userClient.queryUserByIds(teacherIds);
            if (ObjectUtils.isNotEmpty(teacherInfos)){
                vo.setTeacherName(teacherInfos.stream().map(UserDTO::getName).collect(Collectors.joining(",")));
            }
        }
        //5，查询章节信息
        List<CataSimpleInfoDTO> chapterInfo = catalogueClient
                .batchQueryCatalogue(CollUtils.singletonList(question.getChapterId()));
        //5.1，判断章节是否存在
        if (!ObjectUtils.isEmpty(chapterInfo)){
            vo.setChapterName(chapterInfo.get(0).getName());
        }
        //返回
        return vo;
    }

    /**1
     * 管理端分页查询互动问题列表
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> pageQuestion(QuestionAdminPageQuery query) {
        // 1,调用ES处理课程名称，得到课程ID集合
        List<Long> couseIds = null;
        if (ObjectUtils.isNotEmpty(query.getCourseName())) {
            couseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if (ObjectUtils.isEmpty(couseIds)) {
                return PageDTO.empty(0L, 0L);
            }
        }
        //2，分页查询问题列表
        //select * from interaction_question where course_id = #{} and status = ? and create_time between >= ?
        //and order by create_time desc limit ?
        Page<InteractionQuestion> page = this.lambdaQuery()
                .eq(ObjectUtils.isNotEmpty(couseIds),InteractionQuestion::getCourseId, couseIds)
                .eq(ObjectUtils.isNotEmpty(query.getStatus()),InteractionQuestion::getStatus, query.getStatus())
                .eq(ObjectUtils.isNotEmpty(query.getBeginTime()),InteractionQuestion::getCreateTime, query.getBeginTime())
                .eq(ObjectUtils.isNotEmpty(query.getEndTime()),InteractionQuestion::getCreateTime, query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        //2.1，拿到集合
        List<InteractionQuestion> records = page.getRecords();
        //2.2，判断集合是否为空
        if (ObjectUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        //3.set收集各类id
        //用户id
        Set<Long> userIds = new HashSet<>(records.size());
        //课程id
        Set<Long> courseIds = new HashSet<>(records.size());
        //章id
        Set<Long> categoryIds = new HashSet<>(records.size());
        //3.1，遍历集合，收集id
        for (InteractionQuestion record : records) {
            userIds.add(record.getUserId());
            courseIds.add(record.getCourseId());
            categoryIds.add(record.getChapterId());
        }
        //3.2，根据用户id集合查询用户信息
        Map<Long, String> userMap = new HashMap<>(userIds.size());
        List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
        //3.3，判断集合是否为空
        if (ObjectUtils.isNotEmpty(userInfoList)) {
            userMap = userInfoList.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));
        }
        //3.4，根据课程id查询课程信息
        Map<Long, CourseSimpleInfoDTO> courseMap = new HashMap<>(courseIds.size());
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        //3.5，判断集合是否为空
        if (ObjectUtils.isNotEmpty(courseList)) {
            courseMap = courseList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, Function.identity()));
        }
        //3.6，根据章id查询章信息
        Map<Long, String> cataInfoMap = new HashMap<>(categoryIds.size());
        List<CataSimpleInfoDTO> cataInfoList = catalogueClient.batchQueryCatalogue(categoryIds);
        if (ObjectUtils.isNotEmpty(cataInfoList)) {
            cataInfoMap = cataInfoList.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        //4，循环分页数据列表
        List<QuestionAdminVO> voList = new ArrayList<>(records.size());
        //4.1,循环集合，封装vo
        for (InteractionQuestion question : records) {
            //属性拷贝
            QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
            //设置用户昵称
            vo.setUserName(userMap.getOrDefault(question.getUserId(),""));
            //填充课程名称和三级分类信息
            CourseSimpleInfoDTO courseInfo = courseMap.get(question.getCourseId());
            //判断课程信息是否为空
            if (ObjectUtils.isNotEmpty(courseInfo)){
                vo.setCourseName(courseInfo.getName());
                //填充三级分类名称
                vo.setCategoryName(categoryCache.getCategoryNames(courseInfo.getCategoryIds()));
            }
            //4.2填充章节信息
            vo.setChapterName(cataInfoMap.getOrDefault(question.getChapterId(),""));
            vo.setSectionName(cataInfoMap.getOrDefault(question.getSectionId(),""));
            //4.3填充状态
            voList.add(vo);
        }
        //5，封装pagedot并返回
        return PageDTO.of(page, voList);
    }
}

